home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Textures SDK / common / cmdlib.c < prev    next >
C/C++ Source or Header  |  1998-12-02  |  18KB  |  1,023 lines

  1. /***
  2. *
  3. *    Copyright (c) 1998, Valve LLC. All rights reserved.
  4. *    
  5. *    This product contains software technology licensed from Id 
  6. *    Software, Inc. ("Id Technology").  Id Technology (c) 1996 Id Software, Inc. 
  7. *    All Rights Reserved.
  8. *
  9. ****/
  10.  
  11. // cmdlib.c
  12.  
  13. #include "cmdlib.h"
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16.  
  17. #ifdef WIN32
  18. #include <direct.h>
  19. #endif
  20.  
  21. #ifdef NeXT
  22. #include <libc.h>
  23. #endif
  24.  
  25. #ifdef    WIN32
  26. #define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/')
  27. #else    //WIN32
  28. #define PATHSEPARATOR(c) ((c) == '/')
  29. #endif    //WIN32
  30.  
  31. // set these before calling CheckParm
  32. int myargc;
  33. char **myargv;
  34.  
  35. char        com_token[1024];
  36. qboolean    com_eof;
  37.  
  38. qboolean        archive;
  39. char            archivedir[1024];
  40.  
  41.  
  42. /*
  43. =================
  44. Error
  45.  
  46. For abnormal program terminations
  47. =================
  48. */
  49. void Error (char *error, ...)
  50. {
  51.     va_list argptr;
  52.  
  53.     printf ("\n************ ERROR ************\n");
  54.  
  55.     va_start (argptr,error);
  56.     vprintf (error,argptr);
  57.     va_end (argptr);
  58.     printf ("\n");
  59.  
  60.     exit (1);
  61. }
  62.  
  63. // only printf if in verbose mode
  64. qboolean verbose = false;
  65. void qprintf (char *format, ...)
  66. {
  67.     va_list argptr;
  68.  
  69.     if (!verbose)
  70.         return;
  71.     va_start (argptr,format);
  72.     vprintf (format,argptr);
  73.     va_end (argptr);
  74. }
  75.  
  76.  
  77. /*
  78.  
  79. qdir will hold the path up to the quake directory, including the slash
  80.  
  81.   f:\quake\
  82.   /raid/quake/
  83.  
  84. gamedir will hold qdir + the game directory (id1, id2, etc)
  85.  
  86.   */
  87.  
  88. char        qproject[ 1024 ]={'\0'};
  89. char        qdir[1024]={'\0'};
  90. char        gamedir[1024]={'\0'};
  91.  
  92. void SetQdirFromPath (char *path)
  93. {
  94. #ifndef OLD_BOGUS_PATH_CODE
  95.  
  96.     if ( qproject[0]=='\0' )
  97.         {
  98.         if ( getenv("QPROJECT") )
  99.         {
  100.             char c = qproject[ strlen(qproject)-1 ];
  101.             strcpy( qproject, getenv("QPROJECT") );
  102.             if ( !PATHSEPARATOR( c ) )
  103.                 strcat( qproject, "\\" );
  104.         }
  105.         else
  106.             strcpy( qproject, "quiver\\" );
  107.         }
  108.     if ( qproject[0] != '\\' && qproject[0] != '/' && qproject[1] != ':' )
  109.         {
  110.         strcpy( qdir, "\\" );
  111.         }
  112.  
  113.     strcat( qdir, qproject );
  114.     strcpy( gamedir, qdir );
  115.     strcat( gamedir, "\\valve\\" );
  116.  
  117. #else
  118.     char    temp[1024];
  119.     char    *c;
  120.  
  121.     if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
  122.     {    // path is partial
  123.         Q_getwd (temp);
  124.         strcat (temp, path);
  125.         path = temp;
  126.     }
  127.  
  128. // search for "quake" or quiver in path
  129.     if( !qproject[0] ) {
  130.         char *pszProj;
  131.  
  132.         pszProj = getenv("QPROJECT");
  133.  
  134.         if (pszProj != NULL)
  135.             strcpy(qproject, pszProj);
  136.         else
  137.             strcpy(qproject, "quiver");
  138.     }
  139.  
  140. try_again:
  141.  
  142.     for (c=path ; *c ; c++)
  143.     {
  144.         int iSize = 0;
  145.  
  146.         if (!Q_strncasecmp( c, qproject, strlen( qproject ) ) )
  147.             iSize = strlen( qproject ) + 1;
  148.  
  149.         if (iSize > 0) 
  150.         {
  151.             strncpy (qdir, path, c + iSize - path);
  152.             printf ("qdir: %s\n", qdir);
  153.             c += iSize;
  154.             while (*c)
  155.             {
  156.                 if (*c == '/' || *c == '\\')
  157.                 {
  158.                     strncpy (gamedir, path, c+1-path);
  159.                     printf ("gamedir: %s\n", gamedir);
  160.                     return;
  161.                 }
  162.                 c++;
  163.             }
  164.             Error ("No gamedir in %s", path);
  165.             return;
  166.         }
  167.     }
  168.  
  169.     if (!strcmp(qproject, "quiver"))
  170.     {
  171.         strcpy(qproject, "prospero");
  172.         goto try_again;
  173.     }
  174.  
  175.     Error ("SetQdirFromPath: no '%s' in %s", qproject, path);
  176. #endif
  177. }
  178.  
  179.  
  180. char *ExpandArg (char *path)
  181. {
  182.     static char full[1024];
  183.  
  184.     if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
  185.     {
  186.         Q_getwd (full);
  187.         strcat (full, path);
  188.     }
  189.     else
  190.         strcpy (full, path);
  191.     return full;
  192. }
  193.  
  194. char *ExpandPath (char *path)
  195. {
  196.     char *psz;
  197.     static char full[1024];
  198.     if (!qdir)
  199.         Error ("ExpandPath called without qdir set");
  200.     if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
  201.         return path;
  202.     psz = strstr(path, qdir);
  203.     if (psz)
  204.         strcpy(full, path);
  205.     else
  206.         sprintf (full, "%s%s", qdir, path);
  207.  
  208.     return full;
  209. }
  210.  
  211. char *ExpandPathAndArchive (char *path)
  212. {
  213.     char    *expanded;
  214.     char    archivename[1024];
  215.  
  216.     expanded = ExpandPath (path);
  217.  
  218.     if (archive)
  219.     {
  220.         sprintf (archivename, "%s/%s", archivedir, path);
  221.         QCopyFile (expanded, archivename);
  222.     }
  223.     return expanded;
  224. }
  225.  
  226.  
  227. char *copystring(char *s)
  228. {
  229.     char    *b;
  230.     b = malloc(strlen(s)+1);
  231.     strcpy (b, s);
  232.     return b;
  233. }
  234.  
  235.  
  236.  
  237. /*
  238. ================
  239. I_FloatTime
  240. ================
  241. */
  242. double I_FloatTime (void)
  243. {
  244.     time_t    t;
  245.     
  246.     time (&t);
  247.     
  248.     return t;
  249. #if 0
  250. // more precise, less portable
  251.     struct timeval tp;
  252.     struct timezone tzp;
  253.     static int        secbase;
  254.  
  255.     gettimeofday(&tp, &tzp);
  256.     
  257.     if (!secbase)
  258.     {
  259.         secbase = tp.tv_sec;
  260.         return tp.tv_usec/1000000.0;
  261.     }
  262.     
  263.     return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
  264. #endif
  265. }
  266.  
  267. void Q_getwd (char *out)
  268. {
  269. #ifdef WIN32
  270.    _getcwd (out, 256);
  271.    strcat (out, "\\");
  272. #else
  273.    getwd (out);
  274. #endif
  275. }
  276.  
  277.  
  278. void Q_mkdir (char *path)
  279. {
  280. #ifdef WIN32
  281.     if (_mkdir (path) != -1)
  282.         return;
  283. #else
  284.     if (mkdir (path, 0777) != -1)
  285.         return;
  286. #endif
  287.     if (errno != EEXIST)
  288.         Error ("mkdir %s: %s",path, strerror(errno));
  289. }
  290.  
  291. /*
  292. ============
  293. FileTime
  294.  
  295. returns -1 if not present
  296. ============
  297. */
  298. int    FileTime (char *path)
  299. {
  300.     struct    stat    buf;
  301.     
  302.     if (stat (path,&buf) == -1)
  303.         return -1;
  304.     
  305.     return buf.st_mtime;
  306. }
  307.  
  308.  
  309.  
  310. /*
  311. ==============
  312. COM_Parse
  313.  
  314.   Parse a token out of a string (into global: char com_token[1024])
  315. ==============
  316. */
  317. char *COM_Parse (char *data)
  318. {
  319.     int        c;
  320.     int        len;
  321.     
  322.     len = 0;
  323.     com_token[0] = 0;
  324.     
  325.     if (!data)
  326.         return NULL;
  327.         
  328. // skip whitespace
  329. skipwhite:
  330.     while ( (c = *data) <= ' ')
  331.     {
  332.         if (c == 0)
  333.         {
  334.             com_eof = true;
  335.             return NULL;            // end of file;
  336.         }
  337.         data++;
  338.     }
  339.     
  340. // skip // comments
  341.     if (c=='/' && data[1] == '/')
  342.     {
  343.         while (*data && *data != '\n')
  344.             data++;
  345.         goto skipwhite;
  346.     }
  347.     
  348.  
  349. // handle quoted strings specially
  350.     if (c == '\"')
  351.     {
  352.         data++;
  353.         do
  354.         {
  355.             c = *data++;
  356.             if (c=='\"')
  357.             {
  358.                 com_token[len] = 0;
  359.                 return data;
  360.             }
  361.             com_token[len] = c;
  362.             len++;
  363.         } while (1);
  364.     }
  365.  
  366. // parse single characters
  367.     if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
  368.     {
  369.         com_token[len] = c;
  370.         len++;
  371.         com_token[len] = 0;
  372.         return data+1;
  373.     }
  374.  
  375. // parse a regular word
  376.     do
  377.     {
  378.         com_token[len] = c;
  379.         data++;
  380.         len++;
  381.         c = *data;
  382.     if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
  383.             break;
  384.     } while (c>32);
  385.     
  386.     com_token[len] = 0;
  387.     return data;
  388. }
  389.  
  390.  
  391. int Q_strncasecmp (char *s1, char *s2, int n)
  392. {
  393.     int        c1, c2;
  394.     
  395.     while (1)
  396.     {
  397.         c1 = *s1++;
  398.         c2 = *s2++;
  399.  
  400.         if (!n--)
  401.             return 0;        // strings are equal until end point
  402.         
  403.         if (c1 != c2)
  404.         {
  405.             if (c1 >= 'a' && c1 <= 'z')
  406.                 c1 -= ('a' - 'A');
  407.             if (c2 >= 'a' && c2 <= 'z')
  408.                 c2 -= ('a' - 'A');
  409.             if (c1 != c2)
  410.                 return -1;        // strings not equal
  411.         }
  412.         if (!c1)
  413.             return 0;        // strings are equal
  414.     }
  415.     
  416.     return -1;
  417. }
  418.  
  419. int Q_strcasecmp (char *s1, char *s2)
  420. {
  421.     return Q_strncasecmp (s1, s2, 99999);
  422. }
  423.  
  424.  
  425. char *strupr (char *start)
  426. {
  427.     char    *in;
  428.     in = start;
  429.     while (*in)
  430.     {
  431.         *in = toupper(*in);
  432.         in++;
  433.     }
  434.     return start;
  435. }
  436.  
  437. char *strlower (char *start)
  438. {
  439.     char    *in;
  440.     in = start;
  441.     while (*in)
  442.     {
  443.         *in = tolower(*in);
  444.         in++;
  445.     }
  446.     return start;
  447. }
  448.  
  449.  
  450. /*
  451. =============================================================================
  452.  
  453.                         MISC FUNCTIONS
  454.  
  455. =============================================================================
  456. */
  457.  
  458.  
  459. /*
  460. =================
  461. CheckParm
  462.  
  463. Checks for the given parameter in the program's command line arguments
  464. Returns the argument number (1 to argc-1) or 0 if not present
  465. =================
  466. */
  467. int CheckParm (char *check)
  468. {
  469.     int             i;
  470.  
  471.     for (i = 1;i<myargc;i++)
  472.     {
  473.         if ( !Q_strcasecmp(check, myargv[i]) )
  474.             return i;
  475.     }
  476.  
  477.     return 0;
  478. }
  479.  
  480.  
  481.  
  482. /*
  483. ================
  484. filelength
  485. ================
  486. */
  487. int filelength (FILE *f)
  488. {
  489.     int        pos;
  490.     int        end;
  491.  
  492.     pos = ftell (f);
  493.     fseek (f, 0, SEEK_END);
  494.     end = ftell (f);
  495.     fseek (f, pos, SEEK_SET);
  496.  
  497.     return end;
  498. }
  499.  
  500.  
  501. FILE *SafeOpenWrite (char *filename)
  502. {
  503.     FILE    *f;
  504.  
  505.     f = fopen(filename, "wb");
  506.  
  507.     if (!f)
  508.         Error ("Error opening %s: %s",filename,strerror(errno));
  509.  
  510.     return f;
  511. }
  512.  
  513. FILE *SafeOpenRead (char *filename)
  514. {
  515.     FILE    *f;
  516.  
  517.     f = fopen(filename, "rb");
  518.  
  519.     if (!f)
  520.         Error ("Error opening %s: %s",filename,strerror(errno));
  521.  
  522.     return f;
  523. }
  524.  
  525.  
  526. void SafeRead (FILE *f, void *buffer, int count)
  527. {
  528.     if ( fread (buffer, 1, count, f) != (size_t)count)
  529.         Error ("File read failure");
  530. }
  531.  
  532.  
  533. void SafeWrite (FILE *f, void *buffer, int count)
  534. {
  535.     if (fwrite (buffer, 1, count, f) != (size_t)count)
  536.         Error ("File read failure");
  537. }
  538.  
  539.  
  540.  
  541. /*
  542. ==============
  543. LoadFile
  544. ==============
  545. */
  546. int    LoadFile (char *filename, void **bufferptr)
  547. {
  548.     FILE    *f;
  549.     int    length;
  550.     void    *buffer;
  551.  
  552.     f = SafeOpenRead (filename);
  553.     length = filelength (f);
  554.     buffer = malloc (length+1);
  555.     ((char *)buffer)[length] = 0;
  556.     SafeRead (f, buffer, length);
  557.     fclose (f);
  558.  
  559.     *bufferptr = buffer;
  560.     return length;
  561. }
  562.  
  563.  
  564. /*
  565. ==============
  566. SaveFile
  567. ==============
  568. */
  569. void    SaveFile (char *filename, void *buffer, int count)
  570. {
  571.     FILE    *f;
  572.  
  573.     f = SafeOpenWrite (filename);
  574.     SafeWrite (f, buffer, count);
  575.     fclose (f);
  576. }
  577.  
  578.  
  579.  
  580. void DefaultExtension (char *path, char *extension)
  581. {
  582.     char    *src;
  583. //
  584. // if path doesn't have a .EXT, append extension
  585. // (extension should include the .)
  586. //
  587.     src = path + strlen(path) - 1;
  588.  
  589.     while (!PATHSEPARATOR(*src) && src != path)
  590.     {
  591.         if (*src == '.')
  592.             return;                 // it has an extension
  593.         src--;
  594.     }
  595.  
  596.     strcat (path, extension);
  597. }
  598.  
  599.  
  600. void DefaultPath (char *path, char *basepath)
  601. {
  602.     char    temp[128];
  603.  
  604.     if (PATHSEPARATOR(path[0]))
  605.         return;                   // absolute path location
  606.     strcpy (temp,path);
  607.     strcpy (path,basepath);
  608.     strcat (path,temp);
  609. }
  610.  
  611.  
  612. void    StripFilename (char *path)
  613. {
  614.     int             length;
  615.  
  616.     length = strlen(path)-1;
  617.     while (length > 0 && !PATHSEPARATOR(path[length]))
  618.         length--;
  619.     path[length] = 0;
  620. }
  621.  
  622. void    StripExtension (char *path)
  623. {
  624.     int             length;
  625.  
  626.     length = strlen(path)-1;
  627.     while (length > 0 && path[length] != '.')
  628.     {
  629.         length--;
  630.         if (path[length] == '/')
  631.             return;        // no extension
  632.     }
  633.     if (length)
  634.         path[length] = 0;
  635. }
  636.  
  637.  
  638. /*
  639. ====================
  640. Extract file parts
  641. ====================
  642. */
  643. void ExtractFilePath (char *path, char *dest)
  644. {
  645.     char    *src;
  646.  
  647.     src = path + strlen(path) - 1;
  648.  
  649. //
  650. // back up until a \ or the start
  651. //
  652.     while (src != path && !PATHSEPARATOR(*(src-1)))
  653.         src--;
  654.  
  655.     memcpy (dest, path, src-path);
  656.     dest[src-path] = 0;
  657. }
  658.  
  659. void ExtractFileBase (char *path, char *dest)
  660. {
  661.     char    *src;
  662.  
  663.     src = path + strlen(path) - 1;
  664.  
  665. //
  666. // back up until a \ or the start
  667. //
  668.     while (src != path && !PATHSEPARATOR(*(src-1)))
  669.         src--;
  670.  
  671.     while (*src && *src != '.')
  672.     {
  673.         *dest++ = *src++;
  674.     }
  675.     *dest = 0;
  676. }
  677.  
  678. void ExtractFileExtension (char *path, char *dest)
  679. {
  680.     char    *src;
  681.  
  682.     src = path + strlen(path) - 1;
  683.  
  684. //
  685. // back up until a . or the start
  686. //
  687.     while (src != path && *(src-1) != '.')
  688.         src--;
  689.     if (src == path)
  690.     {
  691.         *dest = 0;    // no extension
  692.         return;
  693.     }
  694.  
  695.     strcpy (dest,src);
  696. }
  697.  
  698.  
  699. /*
  700. ==============
  701. ParseNum / ParseHex
  702. ==============
  703. */
  704. int ParseHex (char *hex)
  705. {
  706.     char    *str;
  707.     int    num;
  708.  
  709.     num = 0;
  710.     str = hex;
  711.  
  712.     while (*str)
  713.     {
  714.         num <<= 4;
  715.         if (*str >= '0' && *str <= '9')
  716.             num += *str-'0';
  717.         else if (*str >= 'a' && *str <= 'f')
  718.             num += 10 + *str-'a';
  719.         else if (*str >= 'A' && *str <= 'F')
  720.             num += 10 + *str-'A';
  721.         else
  722.             Error ("Bad hex number: %s",hex);
  723.         str++;
  724.     }
  725.  
  726.     return num;
  727. }
  728.  
  729.  
  730. int ParseNum (char *str)
  731. {
  732.     if (str[0] == '$')
  733.         return ParseHex (str+1);
  734.     if (str[0] == '0' && str[1] == 'x')
  735.         return ParseHex (str+2);
  736.     return atol (str);
  737. }
  738.  
  739.  
  740.  
  741. /*
  742. ============================================================================
  743.  
  744.                     BYTE ORDER FUNCTIONS
  745.  
  746. ============================================================================
  747. */
  748.  
  749. #ifdef _SGI_SOURCE
  750. #define    __BIG_ENDIAN__
  751. #endif
  752.  
  753. #ifdef __BIG_ENDIAN__
  754.  
  755. short   LittleShort (short l)
  756. {
  757.     byte    b1,b2;
  758.  
  759.     b1 = l&255;
  760.     b2 = (l>>8)&255;
  761.  
  762.     return (b1<<8) + b2;
  763. }
  764.  
  765. short   BigShort (short l)
  766. {
  767.     return l;
  768. }
  769.  
  770.  
  771. int    LittleLong (int l)
  772. {
  773.     byte    b1,b2,b3,b4;
  774.  
  775.     b1 = l&255;
  776.     b2 = (l>>8)&255;
  777.     b3 = (l>>16)&255;
  778.     b4 = (l>>24)&255;
  779.  
  780.     return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
  781. }
  782.  
  783. int    BigLong (int l)
  784. {
  785.     return l;
  786. }
  787.  
  788.  
  789. float    LittleFloat (float l)
  790. {
  791.     union {byte b[4]; float f;} in, out;
  792.     
  793.     in.f = l;
  794.     out.b[0] = in.b[3];
  795.     out.b[1] = in.b[2];
  796.     out.b[2] = in.b[1];
  797.     out.b[3] = in.b[0];
  798.     
  799.     return out.f;
  800. }
  801.  
  802. float    BigFloat (float l)
  803. {
  804.     return l;
  805. }
  806.  
  807.  
  808. #else
  809.  
  810.  
  811. short   BigShort (short l)
  812. {
  813.     byte    b1,b2;
  814.  
  815.     b1 = l&255;
  816.     b2 = (l>>8)&255;
  817.  
  818.     return (b1<<8) + b2;
  819. }
  820.  
  821. short   LittleShort (short l)
  822. {
  823.     return l;
  824. }
  825.  
  826.  
  827. int    BigLong (int l)
  828. {
  829.     byte    b1,b2,b3,b4;
  830.  
  831.     b1 = l&255;
  832.     b2 = (l>>8)&255;
  833.     b3 = (l>>16)&255;
  834.     b4 = (l>>24)&255;
  835.  
  836.     return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
  837. }
  838.  
  839. int    LittleLong (int l)
  840. {
  841.     return l;
  842. }
  843.  
  844. float    BigFloat (float l)
  845. {
  846.     union {byte b[4]; float f;} in, out;
  847.     
  848.     in.f = l;
  849.     out.b[0] = in.b[3];
  850.     out.b[1] = in.b[2];
  851.     out.b[2] = in.b[1];
  852.     out.b[3] = in.b[0];
  853.     
  854.     return out.f;
  855. }
  856.  
  857. float    LittleFloat (float l)
  858. {
  859.     return l;
  860. }
  861.  
  862.  
  863. #endif
  864.  
  865.  
  866. //=======================================================
  867.  
  868.  
  869. // FIXME: byte swap?
  870.  
  871. // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
  872. // and the initial and final xor values shown below...  in other words, the
  873. // CCITT standard CRC used by XMODEM
  874.  
  875. #define CRC_INIT_VALUE    0xffff
  876. #define CRC_XOR_VALUE    0x0000
  877.  
  878. static unsigned short crctable[256] =
  879. {
  880.     0x0000,    0x1021,    0x2042,    0x3063,    0x4084,    0x50a5,    0x60c6,    0x70e7,
  881.     0x8108,    0x9129,    0xa14a,    0xb16b,    0xc18c,    0xd1ad,    0xe1ce,    0xf1ef,
  882.     0x1231,    0x0210,    0x3273,    0x2252,    0x52b5,    0x4294,    0x72f7,    0x62d6,
  883.     0x9339,    0x8318,    0xb37b,    0xa35a,    0xd3bd,    0xc39c,    0xf3ff,    0xe3de,
  884.     0x2462,    0x3443,    0x0420,    0x1401,    0x64e6,    0x74c7,    0x44a4,    0x5485,
  885.     0xa56a,    0xb54b,    0x8528,    0x9509,    0xe5ee,    0xf5cf,    0xc5ac,    0xd58d,
  886.     0x3653,    0x2672,    0x1611,    0x0630,    0x76d7,    0x66f6,    0x5695,    0x46b4,
  887.     0xb75b,    0xa77a,    0x9719,    0x8738,    0xf7df,    0xe7fe,    0xd79d,    0xc7bc,
  888.     0x48c4,    0x58e5,    0x6886,    0x78a7,    0x0840,    0x1861,    0x2802,    0x3823,
  889.     0xc9cc,    0xd9ed,    0xe98e,    0xf9af,    0x8948,    0x9969,    0xa90a,    0xb92b,
  890.     0x5af5,    0x4ad4,    0x7ab7,    0x6a96,    0x1a71,    0x0a50,    0x3a33,    0x2a12,
  891.     0xdbfd,    0xcbdc,    0xfbbf,    0xeb9e,    0x9b79,    0x8b58,    0xbb3b,    0xab1a,
  892.     0x6ca6,    0x7c87,    0x4ce4,    0x5cc5,    0x2c22,    0x3c03,    0x0c60,    0x1c41,
  893.     0xedae,    0xfd8f,    0xcdec,    0xddcd,    0xad2a,    0xbd0b,    0x8d68,    0x9d49,
  894.     0x7e97,    0x6eb6,    0x5ed5,    0x4ef4,    0x3e13,    0x2e32,    0x1e51,    0x0e70,
  895.     0xff9f,    0xefbe,    0xdfdd,    0xcffc,    0xbf1b,    0xaf3a,    0x9f59,    0x8f78,
  896.     0x9188,    0x81a9,    0xb1ca,    0xa1eb,    0xd10c,    0xc12d,    0xf14e,    0xe16f,
  897.     0x1080,    0x00a1,    0x30c2,    0x20e3,    0x5004,    0x4025,    0x7046,    0x6067,
  898.     0x83b9,    0x9398,    0xa3fb,    0xb3da,    0xc33d,    0xd31c,    0xe37f,    0xf35e,
  899.     0x02b1,    0x1290,    0x22f3,    0x32d2,    0x4235,    0x5214,    0x6277,    0x7256,
  900.     0xb5ea,    0xa5cb,    0x95a8,    0x8589,    0xf56e,    0xe54f,    0xd52c,    0xc50d,
  901.     0x34e2,    0x24c3,    0x14a0,    0x0481,    0x7466,    0x6447,    0x5424,    0x4405,
  902.     0xa7db,    0xb7fa,    0x8799,    0x97b8,    0xe75f,    0xf77e,    0xc71d,    0xd73c,
  903.     0x26d3,    0x36f2,    0x0691,    0x16b0,    0x6657,    0x7676,    0x4615,    0x5634,
  904.     0xd94c,    0xc96d,    0xf90e,    0xe92f,    0x99c8,    0x89e9,    0xb98a,    0xa9ab,
  905.     0x5844,    0x4865,    0x7806,    0x6827,    0x18c0,    0x08e1,    0x3882,    0x28a3,
  906.     0xcb7d,    0xdb5c,    0xeb3f,    0xfb1e,    0x8bf9,    0x9bd8,    0xabbb,    0xbb9a,
  907.     0x4a75,    0x5a54,    0x6a37,    0x7a16,    0x0af1,    0x1ad0,    0x2ab3,    0x3a92,
  908.     0xfd2e,    0xed0f,    0xdd6c,    0xcd4d,    0xbdaa,    0xad8b,    0x9de8,    0x8dc9,
  909.     0x7c26,    0x6c07,    0x5c64,    0x4c45,    0x3ca2,    0x2c83,    0x1ce0,    0x0cc1,
  910.     0xef1f,    0xff3e,    0xcf5d,    0xdf7c,    0xaf9b,    0xbfba,    0x8fd9,    0x9ff8,
  911.     0x6e17,    0x7e36,    0x4e55,    0x5e74,    0x2e93,    0x3eb2,    0x0ed1,    0x1ef0
  912. };
  913.  
  914. void CRC_Init(unsigned short *crcvalue)
  915. {
  916.     *crcvalue = CRC_INIT_VALUE;
  917. }
  918.  
  919. void CRC_ProcessByte(unsigned short *crcvalue, byte data)
  920. {
  921.     *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
  922. }
  923.  
  924. unsigned short CRC_Value(unsigned short crcvalue)
  925. {
  926.     return crcvalue ^ CRC_XOR_VALUE;
  927. }
  928. //=============================================================================
  929.  
  930. /*
  931. ============
  932. CreatePath
  933. ============
  934. */
  935. void    CreatePath (char *path)
  936. {
  937.     char    *ofs, c;
  938.     
  939.     for (ofs = path+1 ; *ofs ; ofs++)
  940.     {
  941.         c = *ofs;
  942.         if (c == '/' || c == '\\')
  943.         {    // create the directory
  944.             *ofs = 0;
  945.             Q_mkdir (path);
  946.             *ofs = c;
  947.         }
  948.     }
  949. }
  950.  
  951.  
  952. /*
  953. ============
  954. QCopyFile
  955.  
  956.   Used to archive source files
  957. ============
  958. */
  959. void QCopyFile (char *from, char *to)
  960. {
  961.     void    *buffer;
  962.     int        length;
  963.  
  964.     length = LoadFile (from, &buffer);
  965.     CreatePath (to);
  966.     SaveFile (to, buffer, length);
  967.     free (buffer);
  968. }
  969.  
  970.  
  971. /*
  972. ============
  973. ListPak
  974.  
  975.  Prints the contents of the specified pak file to stdout
  976. ============
  977. */
  978.  
  979. void ListPak(char* pakname)
  980. {
  981.     FILE* f = SafeOpenRead(pakname);
  982.     packheader_t head;
  983.     packfile_t* pdir;
  984.     long i=0,imax=0;
  985.     long totlen=0;
  986.  
  987.     SafeRead(f,&head,sizeof(packheader_t));
  988.     pdir=malloc(head.dirlen);
  989.  
  990.     fseek(f,head.dirofs,SEEK_SET);
  991.     SafeRead(f,pdir,head.dirlen);
  992.     
  993.     fseek(f,0,SEEK_END);
  994.     totlen=ftell(f);
  995.  
  996.     fclose(f);
  997.  
  998.     imax=head.dirlen/sizeof(packfile_t);
  999.  
  1000.     for(i;i<imax;i++)
  1001.     {
  1002.         printf ("%64s : %7i\n", pdir[i].name,pdir[i].filelen);
  1003.     }
  1004.  
  1005.     printf("Total Length: %li bytes\n",totlen);
  1006. }
  1007.  
  1008.  
  1009.  
  1010. long flen(FILE* f)
  1011. {
  1012.     long savepos=ftell(f);
  1013.     long filelen=0;
  1014.  
  1015.     fseek(f,0,SEEK_END);
  1016.     filelen=ftell(f);
  1017.  
  1018.     fseek(f,savepos,SEEK_SET);
  1019.     return filelen;
  1020. }
  1021.  
  1022.  
  1023.